#pragma once
#include"net.hpp"
#include"message.hpp"

using namespace MuduoNet;
using namespace Message;
using namespace std;

namespace Dispatch
{
    class CallBack
    {
        public:
        using ptr=shared_ptr<CallBack>;
        virtual void OnMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)=0;
    };
    template<typename T>//子类 模版函数
    class CallBackT:public CallBack
    {
        public:
        using ptr=shared_ptr<CallBackT<T>>;
        using MessageCB=function<void(const BaseConnection::ptr& conn,shared_ptr<T>& msg)>;

        CallBackT(const MessageCB& handler):_handler(handler)
        {}
        void OnMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)    override
        {
            auto type_msg=dynamic_pointer_cast<T>(msg);
            _handler(conn,type_msg);
        }
        private:
        MessageCB _handler;
    };
    class Dispatcher
    {
        public:
        using ptr=shared_ptr<Dispatcher>;
        template<typename T>
        void RegisterHander(Mtype mtype,const typename CallBackT<T>::MessageCB &handler)
        {
            unique_lock<mutex> lock(_mutex);
            auto cb=make_shared<CallBackT<T>>(handler);
            _handler.insert(make_pair(mtype,cb));
        }
        void OnMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)
        {
            unique_lock<mutex> lock(_mutex);
            //找到对应的消息类型对应的回调函数
            auto it=_handler.find(msg->GetMtype());
            if(it!=_handler.end())
            {
               return  it->second->OnMessage(conn,msg);
            }
            //没有找到指定类型的回调函数---因为服务端和客服端都是我们设置的，因此不能出现这种情况
            ELog("收到未知消息");
            conn->ShutDown();
        }
        private:
            mutex _mutex;
            unordered_map<Mtype,CallBack::ptr> _handler;
    };
}